using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml;
using Graphe;
using Graphe.Collations;
using Graphe.Collations.Commands;
using Graphe.Windows.Controls;

namespace Graphe.WPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Constructor

        /// <summary>
        /// Default constructor.
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
            this.Closing += new CancelEventHandler(MainWindow_Closing);
        }

        #endregion
        #region Private Instance Fields

        private double _zoomFactor = 1;
        private DocumentImage _currentImage;
        private double _originalImageHeight;
        private double _originalImageWidth;
		private Nullable<Point> _previousPosition;
		private Cursor _previousCursor;
        private DocumentGroupCollection _manuscriptGroups;
        private Collation _currentCollation;
        private double _openPositionOfCollation = 300;
        private bool _collationControllerInitialized;

        #endregion

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {

            Collation collation = new Collation();

            Manuscript manuscript0 = new Manuscript("C", null);
            Manuscript manuscript1 = new Manuscript("D", null);
            Manuscript manuscript2 = new Manuscript("E", null);

            ManuscriptCollection manuscripts = new ManuscriptCollection();
            manuscripts.Add(manuscript0);
            manuscripts.Add(manuscript1);
            manuscripts.Add(manuscript2);

            RemoveManuscriptCommand cmd = new RemoveManuscriptCommand(manuscript1, manuscripts);

            collation.Do(cmd);


            collation.Undo();







            Settings.Load();

            string path = System.Configuration.ConfigurationManager.AppSettings["localResourcesPath"] + "Index.xml";
            _manuscriptGroups = new DocumentGroupCollection();

            if (!File.Exists(path))
            {
                MessageBox.Show("Hey David. See if you can find the index file. Hint: Look in a subdirectory for the WPF project.");
                System.Windows.Forms.OpenFileDialog dlg = new System.Windows.Forms.OpenFileDialog();
                dlg.FileName = Settings.Instance.LastIndexPath;
                if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    path = dlg.FileName;
                    Settings.Instance.LastIndexPath = dlg.FileName;
                }
            }

            if (!File.Exists(path))
            {
                MessageBox.Show("Couldn't find it? Well, that's sad.");
            }

            if(!String.IsNullOrEmpty(path))
                _manuscriptGroups.Load(path);

            _treeViewManuscriptGroups.ItemsSource = _manuscriptGroups;

        }

        
        private void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            Settings.Instance.Save();
        }


		private DocumentImage CurrentImage
		{
			get { return _currentImage; }
			set
			{
				if(value != _currentImage)
				{
					_scrollViewer.ScrollToLeftEnd();
					_scrollViewer.ScrollToTop();
					ZoomFactor = 1;

					_currentImage = value;
					if(null == _currentImage)
                    {
			            _image.Source = null;
			            _statusBarText.Text = string.Empty;
                    }
					else
					{
                        //You can set the source of the image control to the BitmapFrame on _currentImage, but that
                        //  would be bad. I'm guessing because of the persistant reference to the BitmapFrame, the 
                        //  image resources are never cleaned up. Doh! Loading the image this way each time solves
                        //  the problem.
						BitmapImage img = new BitmapImage(_currentImage.SourceUri);
						_image.Source = img;

                        _originalImageHeight = _currentImage.Frame.Height;
                        _originalImageWidth = _currentImage.Frame.Width;

						ApplyZoomFactor();

                        _statusBarText.Text = "Now Viewing " + _currentImage.FileName + "at " + (ZoomFactor * 100).ToString() + "%";
                    }
				}
			}
		}

        #region Zooming

		private double ZoomFactor
		{
			get { return _zoomFactor; }
			set
			{
				value = Math.Min(value, 4);
				if(value != _zoomFactor)
				{
					_zoomFactor = value;

					ApplyZoomFactor();
				}
			}
		}

		private void ApplyZoomFactor()
		{
			_image.Width = _originalImageWidth * ZoomFactor;
			_image.Height = _originalImageHeight * ZoomFactor;

            if (ZoomFactor != _sliderZoom.Value)
            {
                _sliderZoom.Value = ZoomFactor;
            }
            _statusBarText.Text = "Now Viewing " + _currentImage.FileName + "at " + (ZoomFactor * 100).ToString() + "%";
		}

        private void _buttonZoomIn_Click(object sender, RoutedEventArgs e)
        {
            if (ZoomFactor + .1F > 4)
            {
                MessageBox.Show("You cannot zoom in any more.");
                return;
            }

            ZoomFactor += .05;
        }

        private void _buttonZoomOut_Click(object sender, RoutedEventArgs e)
        {
            if (ZoomFactor - .1F < .05)
            {
                MessageBox.Show("You cannot zoom out any more.");
                return;
            }

            ZoomFactor -= .05;
        }

        private void _sliderZoom_ValueChanged(object sender, RoutedEventArgs e)
        {
            if (_currentImage != null)
            {
				ZoomFactor = _sliderZoom.Value;
            }
        }

        #endregion
        #region Navigation

        private void _buttonMoveLeft_Click(object sender, RoutedEventArgs e)
        {
            //TODO: Implement
        }

        private void _buttonMoveRight_Click(object sender, RoutedEventArgs e)
        {
            //TODO: Implement
        }

        private void SetMoveButtonEnablement()
        {
            //TODO: Implement
        }

        #endregion

        private void _buttonOpenCollation_Click(object sender, RoutedEventArgs e)
        {

            #region Setup Collation Control Controller

            if (!_collationControllerInitialized)
            {
                _collationControllerInitialized = true;

                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonAddSacrum = _buttonAddSacrum;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonEditSacrum = _buttonEditSacrum;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonRemoveSacrum = _buttonRemoveSacrum;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonAddManuscript = _buttonAddManuscript;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonEditManuscript = _buttonEditManuscript;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonRemoveManuscript = _buttonRemoveManuscript;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonAddVariant = _buttonAddVariant;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonEditVariant = _buttonEditVariant;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonRemoveVariant = _buttonRemoveVariant;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonAddReading = _buttonAddReading;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonEditReading = _buttonEditReading;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonRemoveReading = _buttonRemoveReading;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonAddFragment = _buttonAddFragment;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonEditFragment = _buttonEditFragment;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonRemoveFragment = _buttonRemoveFragment;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonAddLacunateMss = _buttonAddLacunateMss;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonEditLacunateMss = _buttonEditLacunateMss;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonRemoveLacunateMss = _buttonRemoveLacunateMss;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonAddNote = _buttonAddNote;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonEditNote = _buttonEditNote;
                Graphe.Windows.Controls.Collations.CollationControl.Controller.ButtonRemoveNote = _buttonRemoveNote;
            }

            #endregion


            System.Windows.Forms.OpenFileDialog dlg = new System.Windows.Forms.OpenFileDialog();
            dlg.FileName = Settings.Instance.LastCollationPath;

            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Settings.Instance.LastCollationPath = dlg.FileName;

                _currentCollation = new Collation();
                _currentCollation.Load(dlg.FileName);

                _collationPanel.Display(_currentCollation);

                _rowDefinitionCollation.Height = new GridLength(200);

            }
        }

        private void _buttonSaveCollation_Click(object sender, RoutedEventArgs e)
        {
            if (_currentCollation == null)
                return;

            System.Windows.Forms.SaveFileDialog dlg = new System.Windows.Forms.SaveFileDialog();

            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _currentCollation.Save(dlg.FileName);

                Collation collationForCompare = new Collation();
                collationForCompare.Load(dlg.FileName);

                int result = _currentCollation.CompareTo(collationForCompare);

                if (result == 0)
                    MessageBox.Show("Collations compared with no problems.");
                else
                    MessageBox.Show("Collations did not compare successfully.");
            }
        }

        private void _buttonOpenFolder_Click(object sender, RoutedEventArgs e)
        {
            //TODO: This now needs to be redefined for the new Local/Remote setup.

            //System.Windows.Forms.FolderBrowserDialog dlg = new System.Windows.Forms.FolderBrowserDialog();
            //dlg.SelectedPath = Settings.Instance.LastDirectory;

            //if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.Cancel)
            //{
            //    LoadImages(dlg.SelectedPath);

            //    Settings.Instance.LastDirectory = dlg.SelectedPath;
            //    Settings.Instance.Save();
            //}
        }

        private void _buttonTools_Click(object sender, RoutedEventArgs e)
        {
            Tools tools = new Tools();

            //TODO: This tool will need the index of the current manuscript. When implemented, hook it up.

            tools.ShowDialog();
        }

        private void _gridSplitter_MouseDoubleClick(object sender, RoutedEventArgs e)
        {
            if (_columnDefinitionThumbnails.Width.Value == 0)
            {
                _columnDefinitionThumbnails.Width = new GridLength(130);
            }
            else
            {
                _columnDefinitionThumbnails.Width = new GridLength(0);
            }
        }

        private void _gridSplitterPicAndCollation_MouseDoubleClick(object sender, RoutedEventArgs e)
        {
            if (_rowDefinitionCollation.Height.Value == 0)
            {
                _rowDefinitionCollation.Height = new GridLength(_openPositionOfCollation);
                _toolBarCollationButtons.Visibility = Visibility.Visible;
            }
            else
            {
                _openPositionOfCollation = _rowDefinitionCollation.Height.Value;
                _rowDefinitionCollation.Height = new GridLength(0);
                _toolBarCollationButtons.Visibility = Visibility.Collapsed;
            }
        }

        private void _image_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (((Keyboard.GetKeyStates(Key.LeftCtrl) | Keyboard.GetKeyStates(Key.RightCtrl)) & KeyStates.Down) != 0)
            {
                if (e.Delta > 0 || (e.Delta < 0 && ZoomFactor - .2 > 0.05))
                {
                    if (e.Delta < 0)
                        ZoomFactor -= .2;
                    else
                        ZoomFactor += .2;
                }
            }
        }


        private void _buttonJump_Click(object sender, RoutedEventArgs e)
        {
            if (_currentImage == null)
            {
                MessageBox.Show("You have not yet selected a manuscript. Pick one by viewing one of its images then come back. Of course that's dumb, so we need to fix that.");
                return;
            }

            //TODO: This will need some reworking once we finish the local/remote storage browser.
            Document manuscript = _manuscriptGroups.FindManuscript(_currentImage.ManuscriptName);

            if (manuscript == null || manuscript.IndexItems == null || manuscript.IndexItems.Count == 0)
            {
                MessageBox.Show("This manuscript does not have indexes, so it has no where to jump to.");
                return;
            }

            Jump jump = new Jump(manuscript);

            jump.ShowDialog();

            if (jump.ImageNumber != 0)
            {
                DocumentImage image = manuscript.FindImage(jump.ImageNumber);

                if (image == null)
                {
                    MessageBox.Show("There was no image that could be found that matched up with that index item.");
                }
                else
                {
                    CurrentImage = image;
                }
            }
        }

        #region Image Dragging

        private void _image_MouseDown(object sender, MouseEventArgs args)
        {
			if(args.LeftButton == MouseButtonState.Pressed)
			{
            _image.CaptureMouse();
            _image.Cursor = Cursors.Hand;
			}
            _previousPosition = args.GetPosition(_scrollViewer);
			_previousCursor = _image.Cursor;
        }

        private void _image_MouseUp(object sender, MouseEventArgs args)
        {
			if(null != _previousPosition)
			{
            _image.ReleaseMouseCapture();
				_image.Cursor = _previousCursor;

				_previousPosition = null;
			}
        }

        private void _image_MouseMove(object sender, MouseEventArgs args)
        {
			if(null != _previousPosition)
            {
                Point newPosition = args.GetPosition(_scrollViewer);
				Vector moved = newPosition - _previousPosition.Value;
                _scrollViewer.ScrollToHorizontalOffset(_scrollViewer.HorizontalOffset - moved.X);
                _scrollViewer.ScrollToVerticalOffset(_scrollViewer.VerticalOffset - moved.Y);
                _previousPosition = newPosition;
            }
        }

        #endregion

        private void _buttonEditIndex(object sender, RoutedEventArgs e)
        {
            //TODO: Implement

            //if (_index == null)
            //{
            //    CreateNewIndexWindow createWindow = new CreateNewIndexWindow();
            //    if (createWindow.ShowDialog() != true)
            //    {
            //        return;
            //    }
            //    else
            //    {
            //        _index = Index.CreateNewIndex(Settings.Instance.LastDirectory, createWindow.IndexName);
            //    }

            //}

            //ManuscriptImage image = _listBoxThumbnails.SelectedItem as ManuscriptImage;

            //if (image != null)
            //{
            //    if (_index.ImageReferences.Contains(image.FileName))
            //    {
            //        ImageReference reference = _index.ImageReferences[image.FileName];
            //        CreateIndexItemWindow dlg = new CreateIndexItemWindow();
            //        dlg.Reference = reference;
            //        reference.FileName = image.FileName;
            //        if (false != dlg.ShowDialog())
            //        {
            //            _index.Save();
            //            image.StartReference = reference.StartReference;
            //            image.EndReference = reference.EndReference;
            //        }
            //    }
            //    else
            //    {
            //        ImageReference reference = new ImageReference();
            //        CreateIndexItemWindow dlg = new CreateIndexItemWindow();
            //        dlg.Reference = reference;
            //        reference.FileName = image.FileName;
            //        if (false != dlg.ShowDialog())
            //        {
            //            _index.ImageReferences.Add(reference);
            //            _index.Save();
            //            image.StartReference = reference.StartReference;
            //            image.EndReference = reference.EndReference;
            //        }
            //    }
            //}
        }

        private void ManuscriptImage_Clicked(object sender, EventArgs args)
        {
            if (sender is Image)
            {
                DocumentImage image = ((sender as Image).Tag as DocumentImage);
                CurrentImage = image;
            }
            else
            {
                DocumentImage image = ((sender as Canvas).Tag as DocumentImage);
                CurrentImage = image;
            }
        }

        private void _gridSplitterPicAndCollation_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if(_rowDefinitionCollation.Height.Value > 25)
                _scrollViewerCollation.Height = _rowDefinitionCollation.Height.Value - 25;
        }

        private void _gridSplitterPicAndCollation_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (_rowDefinitionCollation.Height.Value > 25)
                _scrollViewerCollation.Height = _rowDefinitionCollation.Height.Value - 25;
        }

        #region Collation Buttons

        private void _buttonAddSacrum_Click(object sender, RoutedEventArgs e)
        {
        }

        private void _buttonEditSacrum_Click(object sender, RoutedEventArgs e)
        {
        }

        private void _buttonRemoveSacrum_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonAddManuscript_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonEditManuscript_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonRemoveManuscript_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonAddVariant_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonEditVariant_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonRemoveVariant_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonAddReading_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonEditReading_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonRemoveReading_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonAddFragment_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonEditFragment_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonRemoveFragment_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonAddLacunateMss_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonEditLacunateMss_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonRemoveLacunateMss_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonAddNote_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonEditNote_Click(object sender, RoutedEventArgs e)
        {

        }

        private void _buttonRemoveNote_Click(object sender, RoutedEventArgs e)
        {

        }

        #endregion
    }
}